package web.stu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import web.stu.common.ErrorCode;
import web.stu.exception.BusinessException;
import web.stu.mapper.ClassMapper;
import web.stu.mapper.UserMapper;
import web.stu.model.dto.user.*;
import web.stu.model.entity.User;
import web.stu.model.enums.UserRoleEnum;
import web.stu.model.vo.UserVO;
import web.stu.service.UserService;
import web.stu.util.PasswordUtil;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static web.stu.constant.UserConstant.USER_LOGIN;

/**
 * @author administer
 * @description 针对表【user(用户表)】的数据库操作Service实现
 * @createDate 2025-05-13 19:55:26
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserMapper userMapper;
    private final ClassMapper classMapper;

    public UserServiceImpl(UserMapper userMapper, ClassMapper classMapper) {
        this.userMapper = userMapper;
        this.classMapper = classMapper;
    }

    @Override
    public UserVO login(LoginDTO loginDTO, HttpServletRequest request) {
        // 参数校验
        if (loginDTO.getUsername() == null || loginDTO.getUsername().trim().isEmpty() || loginDTO.getPassword() == null || loginDTO.getPassword().trim().isEmpty()) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "用户名或密码不能为空");
        }

        // 查询用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, loginDTO.getUsername());
        User user = this.getOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "用户名不存在");
        }
        // 判断用户状态 若状态为0 则提示用户已停用，请联系管理员
        if (user.getStatus() == 0) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "用户已停用，请联系管理员");
        }
        // 登录所需权限与用户权限校验
        if (!Objects.equals(user.getRole(), loginDTO.getRole())) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "登录角色错误");
        }

        // 密码校验
        if (!PasswordUtil.matches(loginDTO.getPassword(), user.getPassword())) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "密码错误");
        }

        // 保存登录态到session 中
        request.getSession().setAttribute(USER_LOGIN, user);

        // 转换为VO对象返回
        return UserVO.objToVO(user);
    }

    @Override
    public UserVO register(RegisterDTO registerDTO) {
        // 参数校验
        if (!StringUtils.hasText(registerDTO.getUsername())) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "用户名不能为空");
        }
        if (!StringUtils.hasText(registerDTO.getPassword())) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "密码不能为空");
        }
        if (!StringUtils.hasText(registerDTO.getRealName())) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "真实姓名不能为空");
        }
        // 权限校验 学生可以直接注册，教师注册需要管理员同意，管理员禁止注册
        if (ObjUtil.equals(UserRoleEnum.ADMIN.getValue(), registerDTO.getRole())) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "角色不合法");
        }


        // 检查用户名是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, registerDTO.getUsername());
        if (this.count(queryWrapper) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "用户名已存在");
        }

        // 密码加密处理 采用
        String encryptedPassword = PasswordUtil.encrypt(registerDTO.getPassword());

        // 创建用户对象
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(encryptedPassword);
        user.setRealName(registerDTO.getRealName());
        user.setRole(registerDTO.getRole());

        // 教师注册需要 经过管理员同意
        if (ObjUtil.equals(UserRoleEnum.TEACHER.getValue(), registerDTO.getRole())) {
            // 先设置状态为0 后面再通过管理员同意解开限制
            user.setStatus(0);
        }

        // 保存用户
        if (this.save(user)) {
            log.info("用户注册成功: {}", registerDTO.getUsername());
            return UserVO.objToVO(user);
        } else {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败，请稍后重试");
        }
    }

    @Override
    public UserVO currentLoginUser(HttpServletRequest request) {
        User loginUser = (User) request.getSession().getAttribute(USER_LOGIN);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return UserVO.objToVO(loginUser);
    }

    @Override
    public void logout(HttpServletRequest request) {
        request.getSession().removeAttribute(USER_LOGIN);
    }

    @Override
    public UserVO getUserById(Integer id, HttpServletRequest request) {
        // 非空判断
        if (id == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 查询数据库
        QueryUserDTO queryUserDTO = new QueryUserDTO();
        queryUserDTO.setId(id);

        User oldUser = this.getOne(getQueryWrapper(queryUserDTO, request));
        return UserVO.objToVO(oldUser);
    }

    @Override
    public Page<UserVO> listUsers(QueryUserDTO queryUserDTO, HttpServletRequest request) {
        // 非空判断
        if (ObjUtil.isEmpty(queryUserDTO)) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 获取分页信息
        long current = queryUserDTO.getCurrent();
        long pageSize = queryUserDTO.getPageSize();
        Page<User> userPage = new Page<>(current, pageSize);
        Page<User> page = this.page(userPage, this.getQueryWrapper(queryUserDTO, request));
        List<User> userList = page.getRecords();
        List<UserVO> userVOList = userList.stream().map(UserVO::objToVO).collect(Collectors.toList());
        Page<UserVO> userVOPage = new Page<>(current, pageSize, page.getTotal());
        userVOPage.setRecords(userVOList);

        return userVOPage;
    }

    @Override
    public UserVO updateUser(UpdateUserDTO updateUserDTO, HttpServletRequest request) {
        // 非空判断
        if (ObjUtil.isEmpty(updateUserDTO) || updateUserDTO.getId() == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 根据id获取用户信息
        User oldUser = this.getById(updateUserDTO.getId());
        if (oldUser == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "用户不存在");
        }
        User user = new User();
        BeanUtil.copyProperties(updateUserDTO, user);

        // 若不为管理员，不能修改role 以及状态
        User loginUser = this.getLoginUser(request);
        if (!isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey()) && !ObjectUtil.isAllEmpty(updateUserDTO.getStatus(), updateUserDTO.getRole())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "仅管理员能修改角色与状态");
        }
        // 执行修改
        boolean res = this.updateById(user);
        if (!res) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "修改用户信息失败");
        }
        return UserVO.objToVO(user);
    }

    @Override
    public Boolean deleteUserById(Integer id, HttpServletRequest request) {
        // 非空判断
        if (id == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 直接删除用户信息
        return this.removeById(id);
    }


    @Override
    public Boolean isCompareRole(User user, String role) {
        if (user == null) {
            return false;
        }
        // 通过对应的字符串获取对应的角色值
        Integer value = Objects.requireNonNull(UserRoleEnum.getEnumByValue(role)).getValue();
        return user.getRole().equals(value);
    }


    @Override
    public User getLoginUser(HttpServletRequest request) {
        User loginUser = (User) request.getSession().getAttribute(USER_LOGIN);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        } else {
            return loginUser;
        }
    }

    @Override
    public UserVO addUser(AddUserDTO addUserDTO, HttpServletRequest request) {
        // 非空判断
        if (ObjUtil.isEmpty(addUserDTO) || StrUtil.isBlank(addUserDTO.getUsername())) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 判断用户角色，只能管理员添加用户
        User loginUser = this.getLoginUser(request);
        if (!this.isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "只能管理员添加用户");
        }
        // 判断用户是否已经存在
        long count = this.count(new QueryWrapper<User>().eq("username", addUserDTO.getUsername()));
        if (count > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "用户已存在");
        }

        // 数据转化
        User user = new User();
        BeanUtil.copyProperties(addUserDTO, user);
        // 设置默认的密码 12345
        String encrypt = PasswordUtil.encrypt("12345");
        user.setPassword(encrypt);
        // 插入
        boolean res = this.save(user);
        if (!res) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "添加用户失败");
        }

        return UserVO.objToVO(user);
    }

    @Override
    public List<UserVO> getUsersByClassId(Integer classId, HttpServletRequest request) {
        // 非空校验
        if (ObjUtil.isEmpty(classId)) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        List<Integer> userIds = classMapper.getUsersByClassId(classId);
        List<User> userList = Collections.emptyList();
        if (CollUtil.isNotEmpty(userIds)) {
            userList = listByIds(userIds);
        }

        return userList.stream().map(UserVO::objToVO).collect(Collectors.toList());
    }

    private QueryWrapper<User> getQueryWrapper(QueryUserDTO queryUserDTO, HttpServletRequest request) {
        Integer id = queryUserDTO.getId();
        String username = queryUserDTO.getUsername();
        String realName = queryUserDTO.getRealName();
        Integer role = queryUserDTO.getRole();
        String phone = queryUserDTO.getPhone();
        Integer status = queryUserDTO.getStatus();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq(id != null, "id", id);
        userQueryWrapper.like(StrUtil.isNotBlank(username), "username", username);
        userQueryWrapper.like(StrUtil.isNotBlank(realName), "real_name", realName);
        userQueryWrapper.eq(role != null, "role", role);
        userQueryWrapper.like(StrUtil.isNotBlank(phone), "phone", phone);
        // 如果不为管理员 过滤掉状态为0的用户
        User loginUser = this.getLoginUser(request);
        if (!isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey())) {
            userQueryWrapper.eq("status", 1);
        }
        return userQueryWrapper;
    }


}




